package com.hnas.eCard.web;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hnas.account.orm.Account;
import com.hnas.account.service.AccountService;
import com.hnas.api.dto.DTOResult;
import com.hnas.api.util.CommonUtil;
import com.hnas.common.domain.CoreTradeType;
import com.hnas.common.outdto.GetBalanceReceive;
import com.hnas.common.outdto.InitOrderForm;
import com.hnas.common.outdto.InitOrderReturnReceive;
import com.hnas.common.outdto.RechargePayForm;
import com.hnas.common.outdto.RechargePayReceive;
import com.hnas.common.outdto.SearchRecgPayInfoForm;
import com.hnas.common.outdto.SearchRecgPayInfoReceive;
import com.hnas.common.returndto.RechargeBackReturn;
import com.hnas.common.util.CommonConstants;
import com.hnas.common.util.CommonReturn;
import com.hnas.common.util.CommonUtils;
import com.hnas.common.util.PostServerInfoGet;
import com.hnas.common.util.ResultCode;
import com.hnas.core.util.DateUtil;
import com.hnas.core.util.StringUtil;
import com.hnas.eCard.domain.ECardCommonFinalValue;
import com.hnas.trade.domain.FinalValueUtil;
import com.hnas.trade.domain.OrderStatus;
import com.hnas.trade.domain.OrderType;
import com.hnas.trade.domain.PayStatus;
import com.hnas.trade.domain.PaymentType;
import com.hnas.trade.domain.RechargeStatus;
import com.hnas.trade.domain.TradeRemindThread;
import com.hnas.trade.domain.TradeType;
import com.hnas.trade.dto.DTOOrder;
import com.hnas.trade.dto.DTOTradeRecord;
import com.hnas.trade.orm.TradeRecord;
import com.hnas.trade.service.OrderService;
import com.hnas.trade.service.TradeRecordService;
import com.hnas.trade.util.OrderNoUtil;

/**
 * 电子卡充值Controller
 * <p>
 * Title:ECardRechargeController
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Componay:
 * </p>
 * 
 * @author zhd.yu
 * @date 2018-03-01 09:18:20
 */
@Controller
@RequestMapping("/ecard/recharge")
public class ECardRechargeController {

	private static Log log = LogFactory.getLog(ECardRechargeController.class);
	
	private static ObjectMapper objectMapper = new ObjectMapper();

	@Value("#{component['recharge']}")
	private String orderType;

	@Value("#{component['recharge_mrch_id']}")
	private String mrchId = "10005";

	@Value("#{component['subCode']}") // 发卡类型
	private String subCode;

	@Autowired
	private AccountService accountService;
	@Autowired
	private OrderService orderService;
	@Autowired
	private PostServerInfoGet postServerInfoGet;
	@Autowired
	private TradeRecordService tradeRecordService;

	@RequestMapping(value = "/createRechargeOrder", method = RequestMethod.POST)
	@ResponseBody
	/**
	 * 生成电子卡充值订单 
	 * @Title: createRechargeOrder  
	 * @Description:  
	 * @param request
	 * @return
	 * @throws
	 */
	public String createRechargeOrder(HttpServletRequest request) {
		DTOResult dtoResult = new DTOResult();
		try {
			String sendData = request.getParameter("sendData");
			JSONObject jo = (JSONObject) JSON.parse(sendData);
			String accountId = jo.getString("account_id");
			String amount = jo.getString("amount");
			String frontUrl = jo.getString("front_url");
			String cardNo = jo.getString("card_no");
			String openid = CommonUtil.trimSpecial(jo.getString(ECardCommonFinalValue.openid));
			String payChannel = CommonUtil.trimSpecial(jo.getString("pay_channel"));
			Long amounts = 0l;
			if (StringUtil.isEmpty(accountId)) {
				log.info("电子卡创建充值订单：" + ResultCode.ERROR_012+"-"+ResultCode.getResultValue(ResultCode.ERROR_012));
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_012, null);
			}
			if (StringUtil.isEmpty(amount)) {
				log.info("电子卡创建充值订单：" + ResultCode.ERROR_055+"-"+ResultCode.getResultValue(ResultCode.ERROR_055));
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_055, null);
			}
			if (StringUtil.isEmpty(frontUrl)) {
				log.info("电子卡创建充值订单：" + ResultCode.ERROR_054+"-"+ResultCode.getResultValue(ResultCode.ERROR_054));
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_054, null);
			}
			try {
				amounts = Long.parseLong(amount);
			} catch (Exception e) {
				e.printStackTrace();
				log.info("电子卡创建充值订单异常：" + e.getMessage());
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_055, null);
			}
			Account account = this.accountService.findById(accountId);
			if (null == account) {//根据用户id获取用户信息
				log.info("电子卡创建充值订单：" + ResultCode.ERROR_056+"-"+ResultCode.getResultValue(ResultCode.ERROR_056));
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_056, null);
			}
			//创建订单
			DTOOrder orderDto = createECardRechargeOrder(accountId, amounts, account.getUserName(), cardNo);
			this.orderService.saveOrUpdate(orderDto);
			//调用创建充值订单接口
			InitOrderForm form = new InitOrderForm();
			form.setBody(orderDto.getOrderDetail());
			form.setCardNo(cardNo);
			form.setRechargeType(subCode);
			form.setPayChannel(payChannel);
			form.setTotal(String.valueOf(amounts / 100.0));
			//调用创建充值订单接口
			CommonReturn commonReturn1 = postServerInfoGet.initOrder(form);
			String resultCode1 = commonReturn1.getResultCode();
			if (ResultCode.ERROR_133.equals(commonReturn1.getResultCode())) {
				orderDto.setOrderStatus(OrderStatus.PayFail.getStatus());
				orderDto.setPayStatus(PayStatus.PayFail.getStatus());
				this.orderService.saveOrUpdate(orderDto);
				log.info("电子卡创建充值订单：" + ResultCode.ERROR_133+"-"+ResultCode.getResultValue(ResultCode.ERROR_133));
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_133, null);
			}
			if (!ResultCode.SUCCESS.equals(resultCode1)) {
				log.info("电子卡创建充值订单：" + ResultCode.ERROR_040+"-"+ResultCode.getResultValue(ResultCode.ERROR_040));
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_040, null);
			}
			InitOrderReturnReceive initOrderReturnReceive = (InitOrderReturnReceive) commonReturn1.getResultData();
			orderDto.setSwiftNumber(initOrderReturnReceive.getSwiftNumber());
			orderDto.setUpdateTime(DateUtil.dateTimeToString(new Date()));
			this.orderService.saveOrUpdate(orderDto);
			//调用充值支付接口
			RechargePayForm form2 = new RechargePayForm();
			String frontUrl1 = frontUrl + orderDto.getOrderNo();
			form2.setFrontUrl(frontUrl1);
			form2.setMerchantId(orderDto.getMrchId());
			form2.setUserId(openid);
			form2.setSwiftNumber(orderDto.getSwiftNumber());
			CommonReturn commonReturn2 = postServerInfoGet.rechargePay(form2);
			String resultCode2 = commonReturn2.getResultCode();
			if(!ResultCode.SUCCESS.equals(resultCode2)){
				log.info("电子卡创建充值订单：" + ResultCode.ERROR_041+"-"+ResultCode.getResultValue(ResultCode.ERROR_041));
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_041, null);
			}
			RechargePayReceive rechargePayReceive = (RechargePayReceive) commonReturn2.getResultData();
			//返回前端
			dtoResult.setResultCode(ResultCode.SUCCESS);
			dtoResult.setResultMsg(ResultCode.getResultValue(ResultCode.SUCCESS));
			JSONObject data = new JSONObject();
			data.put("amount",rechargePayReceive.getAmount());
			data.put("card_no",rechargePayReceive.getCardNo());
			data.put("prepay_id",rechargePayReceive.getPrepayId());
			data.put("swift_number",rechargePayReceive.getSwiftNumber());
			data.put("order_no",orderDto.getOrderNo());
			data.put("pay_channel", initOrderReturnReceive.getPayChannel());
			return CommonUtils.createResult(dtoResult, ResultCode.SUCCESS, objectMapper.writeValueAsString(data));
		} catch (Exception e) {
			e.printStackTrace();
			log.info("创建电子卡充值订单异常：" + e.getMessage());
			return CommonUtils.createResult(dtoResult, ResultCode.FAIL, null);
		}
	}

	/**
	 * 创建电子卡充值订单对象
	 * @Title: createECardRechargeOrder  
	 * @Description:  
	 * @param accountId
	 * @param amounts
	 * @param userName
	 * @param cardNo
	 * @return
	 * @throws
	 */
	private DTOOrder createECardRechargeOrder(String accountId, Long amounts, String userName, String cardNo) {
		DTOOrder orderDto = new DTOOrder();
		String orderType = OrderType.Recharge.getType();
		orderDto.setId(CommonUtils.getUUID());
		orderDto.setAccId(accountId);
		orderDto.setAccName(userName);
		orderDto.setCardNo(cardNo);
		orderDto.setCommidityId("");
		orderDto.setCommidityName("充值");
		orderDto.setNeedPay(amounts);
		orderDto.setRealPay(amounts);
		orderDto.setOrderNo(OrderNoUtil.createOrderNo(accountId, orderType));// TODO 生成订单号的工具方法
		orderDto.setOrderStatus(OrderStatus.Unpay.getStatus());
		orderDto.setPayStatus(PayStatus.Unpay.getStatus());
		orderDto.setOrderType(orderType);
		orderDto.setOrderParentType(OrderType.getOrderType(orderType).getParentType());
		orderDto.setOrderTypeName(OrderType.getOrderTypeName(orderType));
		orderDto.setPayment(PaymentType.WX.getType());
		orderDto.setTradeType(TradeType.WXH5.getType());//
		orderDto.setMrchId(mrchId);
		orderDto.setMrchName(FinalValueUtil.WeChatVirtualCard_MrchName);
		orderDto.setSubId(subCode);
		orderDto.setCreateTime(DateUtil.dateTimeToString(new Date()));
		orderDto.setUpdateTime(DateUtil.dateTimeToString(new Date()));
		orderDto.setIsDeleted(false);
		orderDto.setCoreTradeType(CoreTradeType.Recharge_ZC.getType());
		orderDto.setCoreTradeSubType(CoreTradeType.Recharge_ZC.getSubType());
		orderDto.setRechChannel("01");
		return orderDto;
	}
	
	/**
	 * 供微信段调用查询微信充值结果
	 * @param request
	 * @return
	 * @throws JsonProcessingException 
	 */
	@SuppressWarnings("finally")
	@ResponseBody
	@RequestMapping(value="/searchRechargeReturn",method = RequestMethod.POST)
	public String searchRechargeReturn(HttpServletRequest request) throws JsonProcessingException {
		DTOResult dtoResult = new DTOResult();
		try {
			RechargeBackReturn dto = new RechargeBackReturn();
			String sendData = request.getParameter("sendData");
			JSONObject jo = (JSONObject) JSON.parse(sendData);
			String order_no = jo.getString("order_no");
			if(StringUtil.isEmpty(order_no)){
				log.error("查询充值返回结果：orderNo为空");
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_048, null);
			}
			//根据orderNo获取订单
			DTOOrder orderDto = this.orderService.getByOrderNo(order_no);
			if(null==orderDto){
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_047, null);
			}
			
			//判断是否已经支付
			if(PayStatus.Payed.getStatus().equals(orderDto.getOrderStatus())){
				log.info("充值轮循:"+orderDto.getOrderNo()+"已经支付！！");
				dto = rechargeBackReturn(orderDto, OrderStatus.Payed.getStatus(),null);
				return CommonUtils.createResult(dtoResult, ResultCode.SUCCESS, objectMapper.writeValueAsString(dto));
			}
			
			log.info("充值轮循:"+orderDto.getOrderNo()+"未已经支付！！");
			//1，调用查询充值交易订单信息
			SearchRecgPayInfoForm form = new SearchRecgPayInfoForm();
			form.setSwiftNumber(orderDto.getSwiftNumber());
			CommonReturn commonReturn = postServerInfoGet.searchRecgPayInfo(form);
			String resultCode = commonReturn.getResultCode();
			if(ResultCode.FAIL.equals(resultCode)){//查询支付接口异常
				System.out.println("核心查询支付接口失败！");
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_063, null);
			}
			SearchRecgPayInfoReceive searchRecgPayInfoReceive = (SearchRecgPayInfoReceive) commonReturn.getResultData();
			
			//对象为空 查询异常
			if(null == searchRecgPayInfoReceive){
				System.out.println("searchRecgPayInfoReceive为空");
				return CommonUtils.createResult(dtoResult, ResultCode.ERROR_063, null);
			}
			
			//判断是否支付
			if(PayStatus.Payed.getStatus().equals(searchRecgPayInfoReceive.getTradeState())){//支付成功
			      if(RechargeStatus.Recharged.getStatus().equals(searchRecgPayInfoReceive.getRechargeStatus())){//充值成功
		    	    dto = rechargeBackReturn(orderDto, OrderStatus.Payed.getStatus(),searchRecgPayInfoReceive);
					//修改订单状态
					saveOrder(OrderStatus.Payed.getStatus(), PayStatus.Payed.getStatus(), searchRecgPayInfoReceive, orderDto);
					dtoResult.setResultCode(ResultCode.SUCCESS);
					dtoResult.setResultMsg(ResultCode.getResultValue(ResultCode.SUCCESS));
					dtoResult.setResultData(objectMapper.writeValueAsString(dto));
					Account account = this.accountService.findById(orderDto.getAccId());
					JSONObject remindData = new JSONObject();
					remindData.put("openIdStr", account.getOpenId());
					remindData.put("modelType", "1");
					remindData.put("payValue", "￥" + orderDto.getRealPay()/100.0);
					remindData.put("cardNo", orderDto.getCardNo());
					remindData.put("tranSno", orderDto.getOrderNo());
					remindData.put("tranTime", orderDto.getTradeEndTime());
					remindData.put("mrchName", orderDto.getMrchName());
					remindData.put("first", CommonConstants.FIRST_2);
					remindData.put("remark", CommonConstants.REMARK_1);
					TradeRemindThread tradeRemind = new TradeRemindThread(remindData);
					Thread thread = new Thread(tradeRemind);
					thread.start();
					log.debug("开始返回查询结果！");
					dto = rechargeBackReturn(orderDto, OrderStatus.Payed.getStatus(),searchRecgPayInfoReceive);
					return CommonUtils.createResult(dtoResult, ResultCode.SUCCESS, objectMapper.writeValueAsString(dto));
		          }
			      //支付成功，但充值失败  异常订单
			      saveOrder(OrderStatus.Paying.getStatus(), PayStatus.Payed.getStatus(), searchRecgPayInfoReceive, orderDto);
			      dto = rechargeBackReturn(orderDto, OrderStatus.ABNORMAL.getStatus(),searchRecgPayInfoReceive);
			      return CommonUtils.createResult(dtoResult, ResultCode.SUCCESS, objectMapper.writeValueAsString(dto));
			}
			//支付失败
			dto = rechargeBackReturn(orderDto, OrderStatus.Unpay.getStatus(),searchRecgPayInfoReceive);
			return CommonUtils.createResult(dtoResult, ResultCode.SUCCESS, objectMapper.writeValueAsString(dto));
		} catch (Exception e) {
			e.printStackTrace();
			dtoResult.setResultCode(ResultCode.ERROR_063);
			dtoResult.setResultMsg(ResultCode.getResultValue(ResultCode.ERROR_063));
		}finally {
			return objectMapper.writeValueAsString(dtoResult);
		}
	}
	

	private RechargeBackReturn rechargeBackReturn(DTOOrder orderDto,String orderStatus,SearchRecgPayInfoReceive searchRecgPayInfoReceive){
		RechargeBackReturn dto = new RechargeBackReturn();
		if(null!=searchRecgPayInfoReceive){
			dto.setCard_no(searchRecgPayInfoReceive.getCardNo());
			dto.setTrade_sno(searchRecgPayInfoReceive.getRechargeNum());
		}else{
			dto.setCard_no(orderDto.getCardNo());
			dto.setTrade_sno(orderDto.getTradeSno());
		}
		dto.setNeed_pay(null!=orderDto.getNeedPay()?(orderDto.getNeedPay()/100.0)+"":"");
		dto.setOrder_no(orderDto.getOrderNo());
		dto.setOrder_status(orderDto.getOrderStatus());
		dto.setOrder_type_name(orderDto.getCommidityName());
		dto.setReal_pay(null!=orderDto.getRealPay()?(orderDto.getRealPay()/100.0)+"":"");
		dto.setPayment(PaymentType.getPaymentTypeString(orderDto.getPayment()));
		dto.setTrade_type(TradeType.getTradeTypeString(orderDto.getTradeType()));
		dto.setSwift_number(orderDto.getSwiftNumber());
		dto.setSub_id(orderDto.getSubId());
		dto.setPay_status(orderDto.getPayStatus());
		return dto;
	}
	
	private void saveOrder(String orderStatus,String payStatus,SearchRecgPayInfoReceive searchRecgPayInfoReceive,DTOOrder orderDto){
		try {
			String tradeSno = searchRecgPayInfoReceive.getRechargeNum();
			orderDto.setTradeSno(tradeSno);
			orderDto.setOrderStatus(orderStatus);
			orderDto.setPayStatus(payStatus);
			orderDto.setUpdateTime(DateUtil.dateTimeToString(new Date()));
			orderDto.setPayEndTime(searchRecgPayInfoReceive.getTransTime());
			orderDto.setTradeEndTime(searchRecgPayInfoReceive.getTransTime());
			String  cardNo = orderDto.getCardNo();//查询余额
			if(StringUtil.isNotEmpty(cardNo)){
				CommonReturn con = postServerInfoGet.getBalanceInfo(cardNo, subCode);
				if(null!=con&&ResultCode.SUCCESS.equals(con.getResultCode())){
					orderDto.setAfterTradeBalance(((GetBalanceReceive)con.getResultData()).getBALANCE());
				}
				orderService.saveOrUpdate(orderDto);//当保存订单出错时不影响返回支付结果
				//先根据流水号查询订单
				TradeRecord findByTradeSno = this.tradeRecordService.findByTradeSno(tradeSno);
				if(findByTradeSno == null && OrderStatus.Payed.getStatus().equals(orderStatus)){
					//之前没有流水对应的交易记录，且该笔交易完成，插入交易记录表
					DTOTradeRecord dtoTradeRecord = new DTOTradeRecord();
					BeanUtils.copyProperties(orderDto, dtoTradeRecord, new String[]{"id"});
					dtoTradeRecord.setId(CommonUtils.getUUID());
					log.info("Recharge");
					this.tradeRecordService.saveOrUpdate(dtoTradeRecord);	
				 }
			}else{
				log.info("searchRechargeReturn方法查询卡号为空！！！");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
